package org.global.basic;

import org.global.AjaxResult;
import org.global.GEntity;
import org.global.basic.specification.ConditionUnitFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.io.Serializable;
import java.util.*;

public abstract class BasicController<ID extends Serializable, T extends GEntity<ID>, P extends ServiceParams<ID, T>, S extends BaseServiceOpImpl<T, ID, P>>
        implements CurdController<ID, T, P, S>, ApplicationContextAware {

    BeanFactory beanFactory;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.beanFactory = applicationContext;
    }

    @Override
    @PostMapping("/insert")
    public AjaxResult insert(@RequestBody P p) {
        return AjaxResult.ok(service().save(p));
    }

    @Override
    @PostMapping("/del")
    public AjaxResult del(@RequestBody P p) {
        return AjaxResult.ok(service().del(p));
    }

    @Override
    @PostMapping("/update")
    public AjaxResult update(@RequestBody P p) throws IllegalAccessException {
        return AjaxResult.ok(service().update(p));
    }

    @Override
    @PostMapping("/all")
    public AjaxResult all(@RequestBody Map<String, Object> allParams) throws NoSuchMethodException {
        Object mode = allParams.get("mode");
        if (mode instanceof String) {
            if ("all".equals(mode.toString())) {
                Optional<List<T>> optional = service().findAll();
                if (optional.isPresent()) {
                    return AjaxResult.ok(allAfter(optional.get()));
                }
                return AjaxResult.ok(null, "数据是空的");
            }
            return AjaxResult.ok(service().findAll(fetchConditionUnit(mode.toString()).createSpec(null)));
        }
        throw new RuntimeException("请输入正确的查询策略");
    }

    @Override
    @PostMapping("/del/id")
    public AjaxResult delAllById(@RequestBody List<ID> id) {
        service().delByIds(id);
        return AjaxResult.define(200, "删除成功");
    }

    @Override
    @PostMapping("/page")
    public AjaxResult page(@RequestBody PageParams pageParams) throws NoSuchMethodException {
        Objects.requireNonNull(pageParams.getMode(), "查询策略参数不能为空");
        Page<T> page = null;
        if ("all".equals(pageParams.getMode())) {
            page = service().page(null, pageParams.getPage(), pageParams.getSize());
        } else {
            ConditionUnitFactory factory = fetchConditionUnit(pageParams.getMode());
            page = service().page(factory.<ID, T>createSpec(pageParams.getBody()), pageParams.getPage(), pageParams.getSize());
        }
        Map<String, Object> map = new HashMap<>();
        map.put("totalElements", page.getTotalElements());
        map.put("totalPages", page.getTotalPages());
        map.put("content", pageAfter(page.getContent()));
        return AjaxResult.ok(map);
    }

    private ConditionUnitFactory fetchConditionUnit(String mode) {
        if (mode != null) {
            Object bean = beanFactory.getBean(mode);
            if (bean instanceof ConditionUnitFactory) {
                return (ConditionUnitFactory) bean;
            }
        }
        throw new NullPointerException("找不到对应的查询策略，请检查参数");
    }

    public Object allAfter(List<T> all) throws NoSuchMethodException {
        return all;
    }

    public Object pageAfter(List<T> page) throws NoSuchMethodException {
        return page;
    }
}
